﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LiveResults.Model;

namespace LiveResults
{
    public partial class FrmOlaMonitor : FrmMonitor
    {
        EventSoftwareOLA softOLA;
        OlaParser m_Parser;
        public FrmOlaMonitor(EventSoftwareOLA soft, MainApp.logDelegate logger)
            : base(soft, logger)
        {
            softOLA = soft;
            logger("Started monitoring " + softOLA.ConnectionType + "..");
            lblCurrentlyMonitoring.Text = "Monitoring OLA-DB at " + softOLA.ConnectionSettings + " for changes";

            m_Parser = new OlaParser(softOLA.GetDBConnection(), softOLA.EventID, softOLA.RaceID, softOLA.ConnectionType);
            m_Parser.OnResult += new ResultDelegate(m_Parser_OnResult);
            m_Parser.OnClass += new ClassDelegate(m_Parser_OnClass);
            m_Parser.OnLogMessage += new MainApp.logDelegate(m_Parser_OnLogMessage);
            m_Parser.Start();

            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmOlaMonitor_FormClosing);
        }

        void m_Parser_OnClass(string className, int courseLength, int numControls, int order, List<ControlStruct> splitControls)
        {
            if (!m_ModelEvent.Classes.ContainsKey(className))
            {
                EventClass ec = new EventClass() { ClassName = className, CourseLength = courseLength, Order = order, RadioControls = null, Runners = new Dictionary<int, Runner>() };
                if (splitControls != null)
                    ec.RadioControls = splitControls.Select(x => new RadioControl() { ControlName = x.Name, ControlCode = x.Code, Upload = true }).ToList();

                m_ModelEvent.Classes.Add(className, ec);
                m_ModelEvent.FireClassChanged(ec);
                m_Logger("[" + className + "] added");
            }
            else
            {
                EventClass ec = m_ModelEvent.Classes[className];
                ec.ClassName = className;
                ec.CourseLength = courseLength;
                ec.Order = order;
                if (splitControls != null)
                    ec.RadioControls = splitControls.Select(x => new RadioControl() { ControlName = x.Name, ControlCode = x.Code, Upload = true }).ToList();
                m_ModelEvent.FireClassChanged(ec);

                m_Logger("[" + className + "] changed");
            }
        }

        void m_Parser_OnLogMessage(string msg)
        {
            m_Logger(msg);
        }

        void m_Parser_OnResult(int id, int SI, string firstName, string lastName, string club, string Class, int start, int time, RunnerStatus status, List<ResultStruct> splits)
        {
            if (!m_ModelEvent.Classes.ContainsKey(Class))
            {
                //New Class!
                EventClass ec = new EventClass() { ClassName = Class, Runners = new Dictionary<int, Runner>(), Upload = true };
                m_ModelEvent.Classes.Add(Class, ec);
                m_ModelEvent.FireClassChanged(ec);
                m_Logger("[" + Class + "] added");
                Runner r = CreateRunner(id, firstName, lastName, club, Class, start, time, status, splits);
                ec.Runners.Add(id, r);
                m_ModelEvent.FireRunnerChanged(r);
            }
            else
            {
                if (!m_ModelEvent.Classes[Class].Runners.ContainsKey(id))
                {
                    //new runner
                    Runner r = CreateRunner(id, firstName, lastName, club, Class, start, time, status, splits);
                    if (time == -2) //split updated
                    {
                        r.Time = -1;
                        r.Status = RunnerStatus.STARTED;
                    }
                    m_ModelEvent.Classes[Class].Runners.Add(id,r);
                    m_ModelEvent.FireRunnerChanged(r);
                    m_Logger("[" + Class + "] Runner " + r.FirstName + " " + r.LastName + " added..");
                }
                else
                {
                    Runner r = m_ModelEvent.Classes[Class].Runners[id];
                    Dictionary<int, int> radioTimes = null;
                    if (splits != null)
                    {
                        radioTimes = splits.ToDictionary(x => x.ControlCode, x => x.Time);
                    }

                    if (time != -2)
                    {
                        if (r.MergeNewValues(start, time, status, r.RadioTimes))
                        {
                            m_ModelEvent.FireRunnerChanged(r);
                            m_Logger("[" + Class + "] Runner " + r.FirstName + " " + r.LastName + " changed..");
                        }
                    }
                    else
                    {
                        if (radioTimes != null)
                        {
                            bool haveChange = false;
                            foreach (var kvp in radioTimes)
                            {
                                if (r.RadioTimes.ContainsKey(kvp.Key))
                                {
                                    if (r.RadioTimes[kvp.Key] != kvp.Value)
                                    {
                                        r.RadioTimes[kvp.Key] = kvp.Value;
                                        haveChange = true;
                                    }
                                }
                                else
                                {
                                    r.RadioTimes.Add(kvp.Key, kvp.Value);
                                    haveChange = true;
                                }
                            }
                            if (haveChange)
                            {
                                m_ModelEvent.FireRunnerChanged(r);
                                m_Logger("[" + Class + "] Runner " + r.FirstName + " " + r.LastName + " splittimechanged..");
                            }
                        }
                    }
                }
            }
        }

        private static Runner CreateRunner(int id, string firstName, string lastName, string club, string Class, int start, int time, RunnerStatus status, List<ResultStruct> splits)
        {
            Runner r = new Runner()
            {
                ID = id,
                FirstName = firstName,
                LastName = lastName,
                ClassName = Class,
                ClubName = club,
                Time = time,
                Status = status,
                StartTime = start,
                RadioTimes = splits == null ? null : splits.ToDictionary(x => x.ControlCode, x => x.Time)
            };
            return r;
        }

        
        private void FrmOlaMonitor_FormClosing(object sender, FormClosingEventArgs e)
        {
            m_Parser.Stop();
        }
    }
}
